﻿using UnityEngine;
using System.Collections;

static class ScreenToWorld
{
    // Scales collider on sent object to specified screen rect
    // Important: this function does not change object's position, see PositionTransform for this
    static public void ScaleCollider(GameObject entity, Rect targetDimensions, float distanceFromCamera = 2.0f)
    {
        if (entity == null) { Debug.LogError("Null reference passed as an entity!"); return; }

        Collider collider = entity.GetComponent<Collider>();
        if (collider == null) { Debug.LogError("Object does not have a collider!"); return; }

        ScaleTransform(collider.transform, collider.bounds, targetDimensions, distanceFromCamera);
    }

    // Scaling object to fit specified screen rect, based on renderer bounds
    static public void ScaleByRenderer(GameObject entity, Rect targetDimensions, float distanceFromCamera = 2.0f)
    {
        if (entity == null) { Debug.LogError("Null reference passed as an entity!"); return; }


        Renderer entityRenderer = entity.GetComponent<Renderer>();
        if (entityRenderer == null) { Debug.LogError("Onject does not have a renderer!"); return; }

        ScaleTransform(entity.transform, entityRenderer.bounds, targetDimensions, distanceFromCamera);
    }

    static public void ScaleNGUISprite(UISprite entity, Rect targetDimensions, float distanceFromCamera = 2.0f)
    {
        if (entity == null) Debug.LogError("Object does not have a UISprite component!");

        entity.cachedTransform.localScale = Vector3.one;
        var spriteSize = entity.relativeSize;
        var bounds = new Bounds(Vector3.zero, new Vector3(spriteSize.x, spriteSize.y, 1.0f));
        ScaleTransform(entity.cachedTransform, bounds, targetDimensions, distanceFromCamera);
    }

    // Set position of an object to point specifying given screen coordinate
    static public void PositionTransform(Transform entity, int x, int y, float distanceFromCamera = 2.0f)
    {
        entity.position = ScreenPointToWorld(x, y, distanceFromCamera);
    }

    // Transform entity to fit specified screen rect, based on sent bounds (mainly for internal purpose)
    static public void ScaleTransform(Transform entity, Bounds bounds, Rect screenRect, float distanceFromCamera = 2.0f)
    {
        Rect worldRect = ScreenRectToWorld(screenRect, distanceFromCamera);
        float factorX = Mathf.Abs(worldRect.width / bounds.size.x);
        float factorY = Mathf.Abs(worldRect.height / bounds.size.y);
        entity.localScale = new Vector3(entity.localScale.x * factorX, entity.localScale.y * factorY, entity.localScale.z);
    }

    // Transform screen rect to world rect... kind of. (mainly for internal purpose)
    static public Rect ScreenRectToWorld(Rect screenRect, float distanceFromCamera)
    {
        Vector3 bottomLeft = ScreenPointToWorld(Mathf.RoundToInt(screenRect.x), Mathf.RoundToInt(screenRect.y), distanceFromCamera);
        Vector3 topRight = ScreenPointToWorld(Mathf.RoundToInt(screenRect.x + screenRect.width), Mathf.RoundToInt(screenRect.y + screenRect.height), distanceFromCamera);

        return new Rect(bottomLeft.x, bottomLeft.y, topRight.x - bottomLeft.x, topRight.y - bottomLeft.y);
    }

    // Convert screen point to world point, simple as that
    static public Vector3 ScreenPointToWorld(int x, int y, float distanceFromCamera = 2.0f)
    {
        Camera mainCamera = Camera.mainCamera != null ? Camera.mainCamera : UICamera.mainCamera;
        if (mainCamera == null) Debug.LogException(new System.Exception("Could not get the main camera object! Camera.mainCamera and UICamera.mainCamera returned null!"));
        return mainCamera.ScreenToWorldPoint(new Vector3(x, y, distanceFromCamera));
    }
}